#include "mesh3d.h"

Mesh3D::Mesh3D(QObject *parent) :
    Object3D(parent)
{
    listNo = 0;
    meshOwner = false;
}

Mesh3D::~Mesh3D()
{
    clearMesh();
}

void Mesh3D::clearMesh()
{
    if (listNo)
        glDeleteLists(listNo, 1);

    if (pmesh && meshOwner)
        delete pmesh;
    pmesh = 0L;
    meshOwner = false;
}
//----------------------------------------------------------

void Mesh3D::loadModel(QString filename, ColorPolicy colorPolicy)
{
    clearMesh();
    Mesh3DCache *cache = Mesh3DCache::instance();
    pmesh = cache->loadMesh(filename);
//    if (!pmesh)
//        pmesh = new Mesh();
    mColorPolicy = colorPolicy;

    setSettingsChanged(); // implements:    emit changed();
}

//void Mesh3D::linkMesh(Mesh *mesh)
//{
//    pmesh = mesh;
//    linked = true;
//    numberOfShapes = pmesh->numberOfShapes();
//    pmesh->setMinMaxValues();
//    emit changed();
//}

//void Mesh3D::copyMesh()
//{
//    if (meshOwner)
//        return;

//    Mesh *tmp = pmesh;
//    clearMesh();
//    pmesh = new Mesh;
//    meshOwner = true;
//    pmesh->setMesh(tmp);
//    numberOfShapes = pmesh->numberOfShapes();
//    pmesh->setMinMaxValues();
//}
//----------------------------------------------------------

void Mesh3D::applySettings()
{
    if (!listNo)
        listNo = glGenLists(1);
    if (!listNo)
        return; // fucking error!!!!

    glNewList(listNo, GL_COMPILE);
    if (pmesh)
        drawMesh();
    glEndList();
}
//----------------------------------------------------------

void Mesh3D::drawMesh()
{
    for (int i=0; i<pmesh->shapes().count(); i++)
    {
        MeshShape *shape = pmesh->shapes()[i];

        if (mColorPolicy == AssignOneColor)
        {
            assignDefColor(shape->material.ambientColor, shape->material.diffuseColor, shape->material.emissiveColor, shape->material.specularColor, shape->material.shininess);
        }
        else if (mColorPolicy == UseModelColors)
        {
            glMaterialfv(GL_FRONT, GL_DIFFUSE, shape->material.diffuseColor);
            glMaterialfv(GL_FRONT, GL_AMBIENT, shape->material.ambientColor);
            glMaterialfv(GL_FRONT, GL_EMISSION, shape->material.emissiveColor);
            glMaterialfv(GL_FRONT, GL_SPECULAR, shape->material.specularColor);
            glMaterialf(GL_FRONT, GL_SHININESS, shape->material.shininess);
        }

        for (int j=0; j<shape->faces.count(); j++)
        {
            MeshFace *face = shape->faces[j];
            glBegin(GL_POLYGON);
            if (shape->normalPerVertex)
            {
                for (int k=0; k<face->vertices.count(); k++)
                {
                    MeshVertex *vertex = face->vertices[k];
                    glNormal3fv(vertex->normal);
                    glVertex3fv(vertex->point);
                }
            }
            glEnd();
        }
    }
}

//----------------------------------------------------------

void Mesh3D::draw()
{
    if (listNo)
    {
        //glDisable(GL_COLOR_MATERIAL);
        glCallList(listNo);
        //glEnable(GL_COLOR_MATERIAL);
    }
}
//----------------------------------------------------------

QVector3D Mesh3D::getMinBounds()
{
//    if (pmesh)
//        return QVector3D(pmesh->getXMin(), pmesh->getYMin(), pmesh->getZMin());
    return QVector3D();
}

QVector3D Mesh3D::getMaxBounds()
{
//    if (pmesh)
//        return QVector3D(pmesh->getXMax(), pmesh->getYMax(), pmesh->getZMax());
    return QVector3D();
}
//----------------------------------------------------------
